package es.unileon.is.finalproyect.dbconnection;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import es.unileon.is.finalproyect.auxiliar.Streams;
import es.unileon.is.finalproyect.exceptions.DatabaseException;
import es.unileon.is.finalproyect.users.User;

import oracle.jdbc.pool.OracleDataSource;

public class ApplicationConnection {
	
	private static final String URL = "jdbc:oracle:thin:@localhost:1521:xe";
	private static final String USERNAME = "evaluadortextos";
	private static final String PASSWORD = "alberto";
	private static final String BACKUP_FILENAME = "backup.dmp";
	private static final String LOGFILE_FILENAME = "backup.log";
	private static final String LOGIC_DIRECTORY = "EXPORT_DIRECTORY";
	private static final String SCHEMA = "EVALUADORTEXTOS";
	
	private static Connection _con = null;
	private static Connection _sysConnection = null;
	
	public static Connection getConnection() throws SQLException{
		if(_con == null){
			OracleDataSource ods = new OracleDataSource();
			ods.setURL(URL);
			_con = ods.getConnection(USERNAME, PASSWORD);
		}
		return _con;
	}
	
	public static void releaseConnection() throws SQLException{
		_con.close();
		_con = null;
	}
	
	public static void makeBackup(User admin) throws DatabaseException{
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		try{
			//cual es el sistema operativo
			String so = System.getProperty("os.name");
			String comando;
			
			//comando para linux
			if (so.equals("Linux")){
				comando = "expdp";
			} else {
				//comando para windows
				comando = "cmd /c expdp";
			}
			//Relleno de opciones
			comando += " " + USERNAME + "/" + PASSWORD 
					+ " dumpfile = " + BACKUP_FILENAME
					+ " logfile = " + LOGFILE_FILENAME
					+ " directory = " + LOGIC_DIRECTORY
					+ " schemas = " + SCHEMA;
			
			String phisicalDirectory = obtainExportsDirectory();
			
			File backup = new File(phisicalDirectory + BACKUP_FILENAME);
			File logfile = new File(phisicalDirectory + LOGFILE_FILENAME);
			if(backup.exists() || logfile.exists()){
				if(backup.exists()){
					backup.delete();
				}
				if(logfile.exists()){
					logfile.delete();
				}
				System.out.println("Deleting previous backup");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
				}
			}
			
			System.out.println("Please wait while backup is being made");
			//Ejecutar el proceso
			Process p = Runtime.getRuntime().exec(comando);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
			}
     
			System.out.println("Backup completed");
		} catch (IOException e){
			throw new DatabaseException("You need to run the program with administration privileges to do this");
		}
	}
	
	public static void moveBackupTo(User admin, String newDirectory) throws DatabaseException{
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
		try{
			System.out.println("Please wait while files are moved");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {

			}
			
			String phisicalDirectory = obtainExportsDirectory();
			
			File backup = new File(phisicalDirectory + BACKUP_FILENAME);
			File outputBackup = new File(newDirectory + BACKUP_FILENAME);
			if(outputBackup.exists()){
				outputBackup.delete();
			}
			outputBackup.createNewFile();
			FileInputStream fis = new FileInputStream(backup);
			FileOutputStream fos = new FileOutputStream(outputBackup);
			fos.write(Streams.inputStreamToByteArray(fis));
			fos.flush();
			fis.close();
			fos.close();
			backup.delete();
			
			File logfile = new File(phisicalDirectory + LOGFILE_FILENAME);
			File outputLogfile = new File(newDirectory + LOGFILE_FILENAME);
			if(outputLogfile.exists()){
				outputLogfile.delete();
			}
			outputLogfile.createNewFile();
			fis = new FileInputStream(logfile);
			fos = new FileOutputStream(outputLogfile);
			fos.write(Streams.inputStreamToByteArray(fis));
			fos.flush();
			fis.close();
			fos.close();
			logfile.delete();
			System.out.println("Files have been moved to directory " + newDirectory);
		} catch (IOException e){
			throw new DatabaseException("You need to run the program with administration privileges to do this");
		} 
	}
	
	public static void restoreBackup(User admin, String backupName) throws DatabaseException{
		if(!admin.isAdministrator()){
			throw new RuntimeException("You do not have enough privileges to perform this operation");
		}
			String phisicalDirectory = obtainExportsDirectory();
			try{
			File backup = new File(phisicalDirectory + BACKUP_FILENAME);
			if(backup.exists()){
				backup.delete();
				System.out.println("Deleting previous backup");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
				}
			}
			backup.createNewFile();
			
			File previousBackup = new File(backupName);
			FileInputStream fis = new FileInputStream(previousBackup);
			FileOutputStream fos = new FileOutputStream(backup);
			fos.write(Streams.inputStreamToByteArray(fis));
			fos.flush();
			fis.close();
			fos.close();
			
			//cual es el sistema operativo
			String so = System.getProperty("os.name");
			String command;
			
			//comando para linux
			if (so.equals("Linux")){
				command = "impdp";
			} else {
				//comando para windows
				command = "cmd /c impdp";
			}
			//Relleno de opciones
			command += " " + USERNAME + "/" + PASSWORD 
					+ " directory = " + LOGIC_DIRECTORY
					+ " dumpfile = " + BACKUP_FILENAME;
			
			System.out.println("Please wait while backup is been restored");
			Process p = Runtime.getRuntime().exec(command);
			System.out.println("Backup succesfully restored");
		
		} catch (IOException e){
			throw new DatabaseException("You need to run the program with administration privileges to do this");
		}
	}
	
	private static String obtainExportsDirectory() throws DatabaseException{
		try {
			PreparedStatement ps = getConnection().prepareStatement("SELECT DIRECTORY_PATH FROM DBA_DIRECTORIES WHERE DIRECTORY_NAME = ?");
			ps.setString(1, LOGIC_DIRECTORY);
			ResultSet rs = ps.executeQuery();
			if(rs.next()){
				return rs.getString(1) + (System.getProperty("os.name").equals("Linux")?"/":"\\");
			} else {
				throw new DatabaseException("There is no exports directory in the database. Please create a directory named \"EXPORTS_DIRECTORY\"");
			}
		} catch (SQLException e){
			throw new DatabaseException(e.getMessage());
		}
	}

}
